﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using ILRuntime.CLR.Method;
using ILRuntime.CLR.TypeSystem;
using UnityEngine;

namespace QPEngine
{
    public static class DllHelper
    { 
        public static void LoadHotfixAssembly()
        {

            string dllAssetName = "code/hotfix.dll";
            string dllPrefabName = "hotfix.dll";
            TextAsset text = (TextAsset)ResourceHelper.LoadTextAsset(dllAssetName, dllPrefabName);
            byte[] dllBytes = text.bytes;


            string pdbAssetName = "code/hotfix.pdb";
            string pdbPrefabName = "hotfix.pdb";
            TextAsset pdbText = (TextAsset)ResourceHelper.LoadTextAsset(pdbAssetName, pdbPrefabName);
            byte[] pdbBytes = pdbText.bytes;

            using (MemoryStream dms = new MemoryStream(dllBytes))
            using (MemoryStream pms = new MemoryStream(pdbBytes))
            {
                Init.Instance.AppDomain.LoadAssembly(dms, pms, new Mono.Cecil.Pdb.PdbReaderProvider());
            }

         
        } 
        public static Assembly LoadNoHotfixAssembly()
        {
            string tmp = "code/";
            string dllSuffix = ".dll";
            string mdbSuffix = ".mdb";

            byte[] dllBytes = null;
            byte[] mdbBytes = null;

            Dictionary<string, byte[]> dllDic = new Dictionary<string, byte[]>();
            Dictionary<string, byte[]> mdbDic = new Dictionary<string, byte[]>();

            DirectoryInfo folder = new DirectoryInfo(PathHelp.AppHotfixResPath + tmp);
            foreach (FileInfo file in folder.GetFiles("*" + AppConst.AssetBundleExtendName))
            {
               // Log.Debug("加载..."+ file.Name);
                string prefabName = file.Name.Replace(AppConst.AssetBundleExtendName, string.Empty);
                string assetName = tmp + prefabName;
                TextAsset text = (TextAsset)ResourceHelper.LoadTextAsset(assetName, prefabName);

                if (assetName.Contains(dllSuffix))
                {
                    dllBytes = text.bytes;
                }
                if (assetName.Contains(mdbSuffix))
                {
                    mdbBytes = text.bytes;
                }
            }

            Assembly assembly = Assembly.Load(dllBytes, mdbBytes);
            return assembly;
        }


        public static Type[] GetHotfixTypes()
        {
            if(!AppConst.DebugMode)
            {

                ILRuntime.Runtime.Enviorment.AppDomain appDomain = Init.Instance.AppDomain;
                if (appDomain == null)
                {
                    return new Type[0];
                }

                return appDomain.LoadedTypes.Values.Select(x => x.ReflectionType).ToArray();
            }
            else
            {

                return ObjectEvents.Instance.HotfixAssembly.GetTypes();
            }
        }

        public static Type[] GetMonoTypes()
        {
            List<Type> types = new List<Type>();
            foreach (Assembly assembly in ObjectEvents.Instance.GetAll())
            {
                types.AddRange(assembly.GetTypes());
            }
            return types.ToArray();
        }


        public static IMethod[] GetMethodInfo(string typeName)
        {
            ILRuntime.Runtime.Enviorment.AppDomain appDomain = Init.Instance.AppDomain;
            if (appDomain == null)
            {
                return new IMethod[0];
            }

            return appDomain.GetType(typeName).GetMethods().ToArray();
        }

        public static IType GetType(string typeName)
        {
            return Init.Instance.AppDomain.GetType(typeName);
        }

    }
}